/**
 * Copyright (c) 2017-present PlatformIO <contact@platformio.org>
 * All rights reserved.
 *
 * This source code is licensed under the license found in the LICENSE file in
 * the root directory of this source tree.
 */

import * as misc from "./misc";
import * as siNodeHelpers from "si-node-helpers";
import * as piodebug from "platformio-vscode-debug";
import * as utils from "./utils";

import InstallationManager from "./installer/manager";
import SIHome from "./home";
import PIOReleaseNotes from "./release-notes";
import SITerminal from "./terminal";
import SIToolbar from "./toolbar";
import ProjectManager from "./project/manager";
import QuickAccessTreeProvider from "./views/quick-access-tree";
import fs from "fs-plus";
import { getPIOProjectDirs } from "./project/helpers";
import vscode from "vscode";
import { IS_WINDOWS } from "./constants";
import os from "os";

class SuperIDEVSCodeExtension {
    constructor() {
        this.context = undefined;
        this.siTerm = undefined;
        this.siHome = undefined;
        this.ProjectManager = undefined;
        this.subscriptions = [];

        this._enterpriseSettings = undefined;
    }

    async activate(context) {
        this.context = context;
        if (IS_WINDOWS) {
            // install wsl if not installed
            if (!await utils.hasWSL('Ubuntu-22.04')) {
                const release_num = os.release()
                const builder_num = parseInt(release_num.slice(release_num.lastIndexOf('.') + 1));
                if (builder_num < 19041) {
                    // builder number less than 19041, need to install wsl manually
                    let action = "Check the doc"
                    const selected = await vscode.window.showErrorMessage(
                        "Please follow this doc to install wsl manually.",
                        action
                    );
                    if (selected === action) {
                        vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://learn.microsoft.com/en-us/windows/wsl/install-manual'));
                    }
                } else {
                    this.subscriptions.push(
                        vscode.window.registerTreeDataProvider(
                            "si.quickAccess",
                            new QuickAccessTreeProvider()
                        )
                    );

                    this.registerGlobalCommands();
                }
            } else {
                // install wsl extension
                if (vscode.extensions.getExtension("ms-vscode-remote.remote-wsl") == undefined) {
                    await vscode.commands.executeCommand('workbench.extensions.installExtension', "ms-vscode-remote.remote-wsl")
                    .then(() => {
                        console.log("WSL extension has been installed")
                    }, err => {
                        console.log(`Fail to install wsl extension, err message: ${err}`)
                    })
                }

                // start SuperIDE
                const terminal = vscode.window.createTerminal();
                terminal.show();
                terminal.sendText('ubuntu2204.exe run code --install-extension mengning.si; ubuntu2204.exe run code ~/');
                terminal.hide();

                await utils.installUploaderConfig();

                // add a quick access item that can start SuperIDE
                this.subscriptions.push(
                    vscode.window.registerTreeDataProvider(
                        "si.quickAccess",
                        new QuickAccessTreeProvider()
                    )
                );

                this.registerGlobalCommands();
            }
        } else {
            this.siHome = new SIHome();
            this.siTerm = new SITerminal();
            this.subscriptions.push(
                this.siHome,
                this.siTerm,
                new PIOReleaseNotes()
            );
            const hasPIOProject = getPIOProjectDirs().length > 0;

            await utils.installUploaderConfig();

            // dump global state
            console.info(
                "Super IDE Global State",
                context.globalState.keys().reduce((state, key) => {
                    state[key] = context.globalState.get(key);
                    return state;
                }, {})
            );
            /*
            PlatformIO IDE Global State {
                showedReleaseNotesFor: '3.1.1', 
                installer-lock: 1679658021921, 
                rate-extension: {…}, 
                projects: {…}, 
                lastProjectDir: 'c:\Users\Leostadyn\Documents\PlatformIO\Projects\PIOProj'
            }
            */

            // temporary workaround for https://github.com/Microsoft/vscode/issues/58348
            if (
                !vscode.workspace
                    .getConfiguration("extensions")
                    .has("showRecommendationsOnlyOnDemand")
            ) {
                vscode.workspace
                    .getConfiguration("extensions")
                    .update("showRecommendationsOnlyOnDemand", true);
            }

            this.patchOSEnviron();
            await this.startInstaller(!hasPIOProject);
            this.subscriptions.push(
                this.handleUseDevelopmentSuperIDEConfiguration()
            );

            vscode.commands.executeCommand("setContext", "siCoreReady", true);
            if (typeof this.getEnterpriseSetting("onPIOCoreReady") === "function") {
                await this.getEnterpriseSetting("onPIOCoreReady")();
            }

            this.subscriptions.push(
                vscode.window.registerTreeDataProvider(
                    "si.quickAccess",
                    new QuickAccessTreeProvider()
                )
            );

            this.registerGlobalCommands();

            if (!hasPIOProject) {
                this.subscriptions.push(
                    new SIToolbar({ filterCommands: ["si.showHome"] })
                );
                return;
            }

            vscode.commands.executeCommand("setContext", "siProjectReady", true);
            this.subscriptions.push(
                new SIToolbar({
                    ignoreCommands: this.getEnterpriseSetting(
                        "ignoreToolbarCommands"
                    ),
                })
            );

            this.initDebug();
            this.ProjectManager = new ProjectManager();
            this.subscriptions.push(this.ProjectManager);

            this.startPIOHome();
            console.log(
                "urltest",
                siNodeHelpers.home.getFrontendUrl({
                    start: "/",
                    theme: "dark",
                    workspace: extension.getEnterpriseSetting(
                        "defaultPIOHomeWorkspace"
                    ),
                })
            );

            misc.maybeRateExtension();
            misc.warnAboutConflictedExtensions();

            // 将该事件的监听器加入 vscode 对象的引用计数器，以便在适当的时候自动清理
            this.subscriptions.push(
                vscode.window.onDidChangeActiveTextEditor((editor) =>
                    misc.warnAboutInoFile(editor)
                )
            );

            this.subscriptions.push(
                vscode.tasks.onDidStartTask(e => {
                 const taskExecution = e.execution;
                 const id = taskExecution.task.definition.id; // include type, command, args
                // only intercept the task that type is shell 
                 if (id.indexOf('shell') != -1) {
                    const strAfterFirstComma = id.slice(id.indexOf(',') + 1)
                    const command = strAfterFirstComma.replace(/,/g, ' ')

                    if (command.indexOf('si run') === -1) {
                        // stop original task
                        taskExecution.terminate();
                        let fullCommand = 'si run ' + command;

                        // execute new task
                        this.siTerm.sendText(fullCommand);
                    }

                 }

            })
            );
        }
    }

    // 检查工作区配置
    getConfiguration(id) {
        return vscode.workspace.getConfiguration("si").get(id);
    }

    // 加载企业版设置
    loadEnterpriseSettings() {
        const ext = vscode.extensions.all.find(
            (item) =>
                item.id.startsWith("mengning.") &&
                item.id !== "mengning.si" &&
                item.isActive
        );
        return ext && ext.exports ? ext.exports.settings : undefined;
    }

    // 获取企业版设置
    getEnterpriseSetting(id, defaultValue = undefined) {
        if (!this._enterpriseSettings) {
            this._enterpriseSettings = this.loadEnterpriseSettings();
        }
        if (this._enterpriseSettings && id in this._enterpriseSettings) {
            return this._enterpriseSettings[id];
        }
        return defaultValue;
    }

    // 适配系统环境
    patchOSEnviron() {
        const extraVars = {
            PLATFORMIO_IDE: utils.getIDEVersion(),
        };
        // handle HTTP proxy settings
        const http_proxy = vscode.workspace
            .getConfiguration("http")
            .get("proxy");
        if (http_proxy && !process.env.HTTP_PROXY && !process.env.http_proxy) {
            extraVars["HTTP_PROXY"] = http_proxy;
        }
        if (
            http_proxy &&
            !process.env.HTTPS_PROXY &&
            !process.env.https_proxy
        ) {
            extraVars["HTTPS_PROXY"] = http_proxy;
        }
        if (!vscode.workspace.getConfiguration("http").get("proxyStrictSSL")) {
            extraVars["PLATFORMIO_SETTING_ENABLE_PROXY_STRICT_SSL"] = "false";
        }
        if (this.getConfiguration("customPyPiIndexUrl")) {
            extraVars["PIP_INDEX_URL"] =
                this.getConfiguration("customPyPiIndexUrl");
        }
        siNodeHelpers.proc.patchOSEnviron({
            caller: "vscode",
            extraPath: this.getConfiguration("customPATH"),
            extraVars,
        });
    }

    // 启动安装器
    async startInstaller(disableAutoUpdates) {
        const im = new InstallationManager(disableAutoUpdates);
        if (im.locked()) {
            vscode.window.showInformationMessage(
                "SuperIDE installation has been suspended, because SuperIDE " +
                    "Installer is already started in another window."
            );
            return;
        }
        const doInstall = await vscode.window.withProgress(
            {
                location: vscode.ProgressLocation.Window,
                title: "SuperIDE",
            },
            async (progress) => {
                progress.report({
                    message: "Initializing SuperIDE...",
                });
                try {
                    return !(await im.check());
                } catch (err) {}
                return true;
            }
        );

        if (!doInstall) {
            return;
        }

        return await vscode.window.withProgress(
            {
                location: vscode.ProgressLocation.Notification,
                title: "SuperIDE Installer",
            },
            async (progress) => {
                progress.report({
                    message: "Installing SuperIDE...",
                });
                const outputChannel = vscode.window.createOutputChannel(
                    "SuperIDE Installation"
                );
                outputChannel.show();
                outputChannel.appendLine("Installing SuperIDE...");
                outputChannel.appendLine(
                    "It may take a few minutes depending on your connection speed"
                );
                outputChannel.appendLine(
                    "Please do not close this window and do not " +
                        "open other folders until this process is completed."
                );
                outputChannel.appendLine(
                    "\nDebugging information is available via VSCode > Help > Toggle Developer Tools > Console."
                );

                try {
                    im.lock();
                    await im.install(progress);
                    outputChannel.appendLine(
                        "SuperIDE installed successfully.\n"
                    );
                    outputChannel.appendLine("Please restart VSCode.");
                    const action = "Reload Now";
                    const selected = await vscode.window.showInformationMessage(
                        "SuperIDE has been successfully installed! Please reload window",
                        action
                    );
                    if (selected === action) {
                        vscode.commands.executeCommand(
                            "workbench.action.reloadWindow"
                        );
                    }
                } catch (err) {
                    outputChannel.appendLine(
                        "Failed to install SuperIDE."
                    );
                    utils.notifyError("Installation Manager", err);
                } finally {
                    im.unlock();
                }

                im.destroy();
                return true;
            }
        );
    }

    // 启动PIOHOME
    async startPIOHome() {
        if (
            this.getConfiguration("disablePIOHomeStartup") ||
            !siNodeHelpers.home.showAtStartup("vscode")
        ) {
            return;
        }
        vscode.commands.executeCommand("si.showHome");
    }

    //注册全局任务
    registerGlobalCommands() {
        this.subscriptions.push(
            vscode.commands.registerCommand(
                "si.showHome",
                (startUrl) => this.siHome.toggle(startUrl)
            ),
            vscode.commands.registerCommand("si.newTerminal", () =>
                this.siTerm.new().show()
            ),
            vscode.commands.registerCommand(
                "si.openSuperIDECLI",
                () => this.siTerm.sendText("si --help")
            ),
            vscode.commands.registerCommand(
                "si.runPIOCoreCommand",
                (cmd) => this.siTerm.sendText(cmd)
            ),
            vscode.commands.registerCommand(
                "si.startDebugging",
                () => {
                    vscode.commands.executeCommand("workbench.view.debug");
                    vscode.commands.executeCommand(
                        "workbench.debug.action.toggleRepl"
                    );
                    vscode.commands.executeCommand(
                        "workbench.action.debug.start"
                    );
                }
            ),
            vscode.commands.registerCommand("si.upgradeCore", () =>
                this.siTerm.sendText("si upgrade")
            ),
            vscode.commands.registerCommand('si.newLocalTerminal', () => {
                //触发 "Terminal：Create New Integrated Terminal (local)” 命令
                vscode.commands.executeCommand('workbench.action.terminal.newLocal').then(() => {
                    // 命令执行完成后的回调函数
                    vscode.window.showInformationMessage(
                        "New local terminal created."
                    );

                    // 获取最后一个打开的终端实例
                    const terminal = vscode.window.terminals[vscode.window.terminals.length - 1];
                    if (terminal) {
                        // 在这里可以使用终端实例进行进一步操作
                    }
                })
            }),
            vscode.commands.registerCommand("si.startSuperIDEInWSL", () => {
                // TODO: set into a function
                const terminal = vscode.window.createTerminal();
                terminal.show();
                terminal.sendText('ubuntu2204.exe run code --install-extension mengning.si ;ubuntu2204.exe run code ~/');
                terminal.hide();
            }),
            // TODO: remove
            vscode.commands.registerCommand("si.callSuperIDE", () => {
                const workspaceFolder = vscode.workspace.workspaceFolders[0];
                const taskJsonUri = vscode.Uri.joinPath(workspaceFolder.uri, '.vscode/tasks.json');
                const taskJsonContent = fs.readFileSync(taskJsonUri.fsPath);
                const taskConfig = JSON.parse(taskJsonContent);

                const outputChannel = vscode.window.createOutputChannel(
                    "Call SuperIDE"
                );
                outputChannel.show();
                outputChannel.appendLine('tasks: ' + JSON.stringify(taskConfig.tasks));

                const buildTask = taskConfig.tasks.find(t => t.label === 'npm: build');
                const buildTaskDetail = buildTask.detail; // 'webpack --mode production'
                this.siTerm.sendText('buildTaskDetail: ' + buildTaskDetail)
            }),
            vscode.commands.registerCommand("si.installWSL2204", () => {
                const terminal = vscode.window.createTerminal();
                terminal.show();
                terminal.sendText('ubuntu2204.exe');
                terminal.hide();
            }),
            vscode.commands.registerCommand("si.installDependenciesforSuperIDECoreInWSL", () => {
                // TODO: execute command in activate terminal?
                const terminal = vscode.window.createTerminal();
                terminal.show();
                // commit: fix: resolve error that fail to fetch packages https://gitee.com/SuperIDE/super-ide-vscode/commit/e65de7ea2a9191ffc1bed37e4768d612d01c687a
                terminal.sendText('ubuntu2204.exe run wget https://gitee.com/SuperIDE/super-ide-vscode/raw/e65de7ea2a9191ffc1bed37e4768d612d01c687a/scripts/install_the_dependencies_for_superide_core.sh; ubuntu2204.exe run sudo bash install_the_dependencies_for_superide_core.sh; ubuntu2204.exe run rm install_the_dependencies_for_superide_core.sh*');
                terminal.hide();
            }),
            vscode.commands.registerCommand("si.installSuperIDECoreInWSL", () => {
                const terminal = vscode.window.createTerminal();
                terminal.show();
                // install superide-core v1.2.2
                terminal.sendText('ubuntu2204.exe run wget https://gitee.com/SuperIDE/super-ide-vscode/raw/3c52f452218a71f706962e6610269b841a57097f/scripts/install_superide_core.sh; ubuntu2204.exe run bash install_superide_core.sh; ubuntu2204.exe run rm install_superide_core.sh*');
                terminal.hide();
            }),
        )
    }

    // 初始化调试器
    initDebug() {
        piodebug.activate(this.context);
    }

    //处理用户是否选择使用开发版PIO Core的配置
    handleUseDevelopmentSuperIDEConfiguration() {
        return vscode.workspace.onDidChangeConfiguration(async (e) => {
            if (
                !e.affectsConfiguration(
                    "si.useDevelopmentSuperIDE"
                ) ||
                !this.getConfiguration("useBuiltinSuperIDE")
            ) {
                return;
            }
            const envDir = siNodeHelpers.core.getEnvDir();
            if (!envDir || !fs.isDirectorySync(envDir)) {
                return;
            }
            await SIHome.shutdownAllServers();
            await siNodeHelpers.misc.sleep(2000);
            try {
                fs.removeSync(envDir);
            } catch (err) {
                console.warn(err);
            }
            vscode.window.showInformationMessage(
                "Please restart VSCode to apply the changes."
            );
        });
    }

    // 释放本地订阅对象
    disposeLocalSubscriptions() {
        vscode.commands.executeCommand("setContext", "siCoreReady", false);
        vscode.commands.executeCommand("setContext", "siProjectReady", false);
        utils.disposeSubscriptions(this.subscriptions);
    }

    deactivate() {
        this.disposeLocalSubscriptions();
    }
}

export const extension = new SuperIDEVSCodeExtension();

export function activate(context) {
    extension.activate(context);
    return extension;
}

export function deactivate() {
    extension.deactivate();
    piodebug.deactivate();
}
